home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Games Collection 1 / software vault.zip / software vault / CDR10 / SPX20.ZIP / SPX_DOC.ZIP / SPX_OBJ.DOC < prev    next >
Text File  |  1993-09-16  |  13KB  |  370 lines

  1. { SPX Library Version 2.0  Copyright 1993 Scott D. Ramsay }
  2.  
  3.   SPX_OBJ is the object handling unit.  It allows a easy way to
  4. keep track of multiple objects.
  5.  
  6.   Each object is a descendent of TOBJS.  All objects are added to a
  7. double linked list for the dynamic creation of numerous objects.  When
  8. removing objects from the list, we add the node to a 'kill' list which
  9. we can quickly deallocate multiple objects.
  10.  
  11.   Plist:  Is our double linked pointer type which its data points to a TOBJS
  12.  
  13.       Type
  14.         Pobjs = ^Tobjs;
  15.         Plist = ^Tlist;
  16.         Tlist = record
  17.                   item      : pobjs;
  18.                   prev,next : plist;
  19.                 end;
  20.  
  21.   Here is the basic structure of the linked lists.  Brackets [] specifies
  22. actual records or objects.
  23.  
  24.   var
  25.     head,tail : Plist;    { Head/Tail pointers to our object list }
  26.     kill      : Pkill;    { Objects that need to be removed from the list }
  27.     add       : Padd;     { Objects that need to be added to the list }
  28.  
  29.                                                           |- Tail
  30.                                                          \|/
  31.     Head -->  [Node1]  <-->  [Node2] <--> [Node3] <--> [Node4] --> NIL
  32.                  |              |            |            |
  33.               [Tobj]         [Tobj]       [Tobj]       [Tobj]
  34.  
  35.  
  36.     Kill -->  [Knode1] --> [Knode2] --> NIL
  37.                  |            |
  38.                 \|/          \|/
  39.               [Node2]      [Node4]
  40.  
  41.     Add  -->  [Anode1] --> [Anode2] --> NIL
  42.                  |            |
  43.                 \|/          \|/
  44.               [NodeA]      [NodeB]
  45.  
  46.  
  47.   In the above example we have four objects in our list.  With the
  48. second and third node in the kill list (ready to be deleted).  The add
  49. list contains two new nodes (NodeA and NodeB) that are read to be
  50. added to the linked list.
  51.  
  52.   That's basically the structure.  To do calcuations on each object, we
  53. just traverse the double linked list.  Lets say that the object at Node2
  54. was a space alien and was shot.  Ok its dead, so we add it to the kill list.
  55.  
  56.   After one iteration,  usually the Kill and Add list is traversed deallocating
  57. and allocating nodes from and to the double linked list.
  58.  
  59.     pkill = ^tkill;
  60.     tkill = record
  61.               tk   : plist;  { TK -  plist pointer To kill }
  62.               next : pkill;
  63.             end;
  64.  
  65.     padd  = ^tadd;
  66.     tadd  = record
  67.               ta    : plist;    { TA - plist pointer to add }
  68.               front : boolean;  { TRUE - add to top of list, else bottom }
  69.               next  : padd;
  70.             end;
  71.  
  72. EXAMPLE GAME STRUCTURE:
  73.  
  74.     repeat
  75.       doAllitems(head,dErase);   { erase objects from work page }
  76.       doAllitems(head,dCalc);    { move, create, kill objects }
  77.       doAllitems(head,dDraw);    { draw objects on work page }
  78.       doAllitems(head,dUpdate);  { copy objects drawn area on work to visual }
  79.       cleanadd_list(add,head,tail); { add new objects to list }
  80.       cleankill_list(kill,head,tail); { delete killed objects from list }
  81.      { frame wait } (* see SPX_TIM.DOC *)
  82.     until gameover;
  83.  
  84. ───────────────────────────────────────────────────────────────────────────
  85.  Type
  86.     TObjs = object;
  87.  
  88.   Generic object type.  TObjs is the base for all objects that
  89.   need to be handled.
  90.  
  91. VARIABLES:
  92.          powner:plist     A pointer to the object's node in the linked list;
  93.          killed:boolean   TRUE if the object was added to a kill list;
  94.          cankill:boolean  Set to TRUE if allowing the object to be added to
  95.                           the kill list. (See checkhit for better descript);
  96.          overshow:boolean In my games I traverse the list twice.  The first
  97.                           time is to display the objects that will be behind
  98.                           my character, the second time is for the objects
  99.                           that are above my character.  Set OVERSHOW to
  100.                           TRUE for the object to be an over character.
  101.                           (In the game RSQUID, the cloud objects are set
  102.                           to TRUE "Always in front", all other objects are
  103.                           set to FALSE. "Behind my main character";
  104.          id:integer       For each object type I assign a unique number.  This
  105.                           is incase I need to find certain objects while
  106.                           traversing the list
  107.  
  108. METHODS:
  109.  
  110.   ---------------------------------------------------
  111.   constructor Tobjs.init;
  112.  
  113.     Sets up the object
  114.  
  115.     DEFAULTS:
  116.        KILLED   set to FALSE
  117.        ID       set to 0
  118.        OVERSHOW set to TRUE
  119.  
  120.     OVERRIDE:  often
  121.  
  122.    Here is how you add an object to the linked list;
  123.  
  124.    var
  125.      p : plist;
  126.    begin
  127.      new(p);                    { Create a new node }
  128.      p^.item := new(Pobjs,init);{ Create the object }
  129.      p^.item^.powner := p;      { IMPORTANT! have the object point to its node }
  130.      addp(head,tail,p);         { Add the node to the list }
  131.    end;
  132.  
  133.   To delay the new node to be added to the list use add2add_list instead
  134.   of "addp".
  135.  
  136.   See the procedure Add2Kill_list for reason for " p^.item^.powner := p;"
  137.   ---------------------------------------------------
  138.   procedure TObjs.drawitemobject;
  139.  
  140.     Displays the item.
  141.  
  142.     OVERRIDE:  often
  143.  
  144.     Tobjs.drawitemobject is an empty function.  In your drawitemobject
  145.   function it will usually draw a sprite or object.
  146.  
  147.   ---------------------------------------------------
  148.   procedure TObjs.calcitemobject;
  149.  
  150.     Does any calcuations to the object such as changing the object's
  151.   position.
  152.  
  153.     OVERRIDE:  often
  154.  
  155.   ---------------------------------------------------
  156.   procedure TObjs.eraseitemobject;
  157.  
  158.     In your eraseitemobject function it will usually erase a sprite or
  159.   object.
  160.  
  161.     OVERRIDE:  often
  162.  
  163.   ---------------------------------------------------
  164.   procedure TObjs.updateitemobject;
  165.  
  166.     In your updateitemobject function it will usually copy the sprite
  167.   or object to the visual screen.  Used often when working with an off
  168.   screen work page.
  169.  
  170.     OVERRIDE:  often
  171.  
  172.   ---------------------------------------------------
  173.   function TObjs.checkhit(hx,hy:integer;item:pobjs):boolean;
  174.  
  175.     Return TRUE if hx,hy is in range of an object.
  176.  
  177.     HX,HY:  Location to check;
  178.     ITEM:   Tobjs that it is in conflict with
  179.  
  180.   OVERRIDE: often
  181.  
  182.    For example:
  183.  
  184.       function TMyObject.checkhit(hx,hy:integer;item:pobjs):boolean;
  185.       begin
  186.         checkhit := (abs(hx-MyObjectX)<10) and (abs(hy-MyObjectY)<10);
  187.       end;
  188.  
  189.     This is basically a collision detection function.  For example,
  190.    Lets assume we have a Tbullet object (desendant of Tobjs) that wants
  191.    to check if it hit anyother objects in the list.  In the procedure
  192.    Tbullet.calcitemobject we would traverse the linked list calling
  193.    the checkhit function for each object in the list.  If the function
  194.    returns TRUE, then the object collided with the object.
  195.  
  196.    procedure Tbullet.calcitemobject;
  197.    var
  198.      p : plist;
  199.    begin
  200.      p := head;
  201.      while p<>nil do
  202.        begin
  203.         { Don't check for colliding bullets or dead objects }
  204.          if (p^.item^.id<>id_bullet) and not p^.item^.killed
  205.            then
  206.              if p^.item^.checkhit(bullet_x,bullet_y,@self)
  207.                then { we hit the object! }
  208.          p := p^.next;
  209.        end;
  210.    end;
  211.  
  212.   ---------------------------------------------------
  213.   destructor TObjs.done;
  214.  
  215.   Deallocates the object;
  216.  
  217.   OVERRIDE: sometimes
  218.  
  219. ───────────────────────────────────────────────────────────────────────────
  220. procedure doallitems(head:plist;m:objmode);
  221.  
  222.   Traverse the linked list calling the an itemobject function in
  223.   each node.
  224.  
  225.   HEAD:     The head pointer of the linked list
  226.   M:        method to call in each node. M is of type objmode:
  227.               where type objmode = (dNothing,dDraw,dErase,dUpdate,dCalc);
  228.  
  229.               dNothing - calls nothing. (just traverses the list)
  230.               dDraw    - calls the drawitemobject procedures
  231.               dErase   - calls the eraseitemobject procedures
  232.               dUpdate  - calls the updateitemobject procedures
  233.               dCalc    - calls the calcitemobject procedures
  234.  
  235.   Example:
  236.  
  237.       doallitems(Head,dCalc);
  238.  
  239.       { calls the calcitemobject procedure in each node }
  240.  
  241.  
  242. ───────────────────────────────────────────────────────────────────────────
  243. procedure addbeg(var nkbeg,nkend,p:plist);
  244.  
  245.   Add a node to the BEGINNING of the linked list
  246.  
  247.   NKBEG:  Linked list Head pointer;
  248.   NKEND:  Linked list Tail pointer;
  249.   P:      Node to add to the list
  250.  
  251. ───────────────────────────────────────────────────────────────────────────
  252. procedure addend(var nkbeg,nkend,p:plist);
  253.  
  254.   Add a node to the END of the linked list
  255.  
  256.   NKBEG:  Linked list Head pointer;
  257.   NKEND:  Linked list Tail pointer;
  258.   P:      Node to add to the list
  259.  
  260. ───────────────────────────────────────────────────────────────────────────
  261. procedure addp(var nkbeg,nkend,p:plist);
  262.  
  263.   Add a node to the END of the linked list.  Same as ADDEND, here for
  264.   compatibility from SPX v1.0.
  265.  
  266.   NKBEG:  Linked list Head pointer;
  267.   NKEND:  Linked list Tail pointer;
  268.   P:      Node to add to the list
  269.  
  270. ───────────────────────────────────────────────────────────────────────────
  271. procedure deletep(var nkbeg,nkend,p:plist);
  272.  
  273.   Delete a note from the list and deallocate the object connected to it
  274.  
  275.   NKBEG:  Linked list Head pointer;
  276.   NKEND:  Linked list Tail pointer;
  277.   P:      Node to delete to the list
  278.  
  279. ───────────────────────────────────────────────────────────────────────────
  280. procedure calcitems(var nkbeg:plist);
  281.  
  282.   Traverses a linked list calling the node's object's calcitemobject method
  283.  
  284.   NKBEG: Linked list Head pointer
  285.  
  286.   NOTE: Still calls method even if the KILLED flag it true.
  287.  
  288. ───────────────────────────────────────────────────────────────────────────
  289. procedure drawitems(var nkbeg:plist;over:boolean);
  290.  
  291.   Traverses a linked list calling the node's object's drawitem object method
  292.  
  293.   NKBEG: Linked list Head pointer
  294.   OVER:  Set to TRUE to call only objects with OVERSHOW set to TRUE
  295.          Set to FALSE to call only objects with OVERSHOW set to FALSE
  296.  
  297. ───────────────────────────────────────────────────────────────────────────
  298. procedure add2add_list(var add:padd;i:plist;front:boolean);
  299.  
  300.   Adds a node to the add list.
  301.  
  302.   ADD:     Add list to add the node
  303.   P:       Note to be added
  304.   FRONT:   Set to TRUE if you want the node to be added to the top
  305.            of the list, else it will be added the the end.
  306.  
  307. ───────────────────────────────────────────────────────────────────────────
  308. procedure cleanadd_list(var add:padd;var nkbeg,nkend:plist);
  309.  
  310.    Traverses the ADD list and adds each node to the linked list.
  311.  
  312.    ADD:    Add list to cleanout
  313.    NKBEG:  Linked list Head pointer
  314.    NKEND:  Linked list Tail pointer
  315.  
  316.    On return ADD=NIL
  317.  
  318. ───────────────────────────────────────────────────────────────────────────
  319. procedure add2kill_list(var kill:pkill;var i:plist);
  320.  
  321.   Adds a node to the kill list and sets the object's KILLED flag to TRUE.
  322.  
  323.   KILL:  Kill list to add the node;
  324.   I:     Node to add to the kill list
  325.  
  326.   This procedure is usually called with in a object's calcitemobject or
  327.   checkhit methods.  Since this is the case, you CAN'T deallocate a
  328.   object while still in the object's method. So by adding the node/object
  329.   to a kill list.  One can remove the object later.
  330.  
  331.   Each object has a pointer to its node (powner) that is passed to the
  332.   kill list.
  333.  
  334.   Example:
  335.  
  336.     function TMyObject.checkhit(hx,hy:integer;item:pobjs):boolean;
  337.       begin
  338.         if (abs(hx-MyObjectX)<10) and (abs(hy-MyObjectY)<10)
  339.           then
  340.             begin
  341.               checkhit := true;
  342.               add2kill_list(kill,powner);
  343.             end
  344.           else checkhit := false;
  345.       end;
  346.  
  347. ───────────────────────────────────────────────────────────────────────────
  348. procedure cleankill_list(var kill:pkill;var nkbeg,nkend:plist);
  349.  
  350.    Traverses the KILL list deallocating node that is in the kill and
  351.    linked list.
  352.  
  353.    KILL:  Kill list to cleanout;
  354.    NKBEG:  Linked list Head pointer;
  355.    NKEND:  Linked list Tail pointer
  356.  
  357.    On return KILL=NIL
  358.  
  359. ───────────────────────────────────────────────────────────────────────────
  360. procedure clean_plist(var nkbeg,nkend:plist);
  361.  
  362.    Traverse the LINKED list deallocating every node.
  363.  
  364.    NKBEG:  Linked list Head pointer;
  365.    NKEND:  Linked list Tail pointer
  366.  
  367.    On return nkbeg=NIL and nkend=NIL
  368.  
  369. ───────────────────────────────────────────────────────────────────────────
  370.